#coding:utf-8

class QueryDomain

  def self.ratio to
    result = []

    JobRepo.all.each do |job|
      organ_id = job["organ"]["id"]
      position_id = job["subject"]["id"]
      job["assign"].each do |user|
        reqs = require_papers(organ_id, position_id)
        regs = register_papers(user["login"])
        valids = PaperRegisterRepo.where(paper_type_id: regs).map do |paper|
          paper if paper.due_date <= to || (paper.due_date - paper.paper_type.delay) <= to
        end.compact.map(&:paper_type_id)
        result << [reqs, regs, valids]
      end
    end

    result = result.inject({}) do |sum, (s, r, v)|
      s.each {|x| sum[x] ||= {}; sum[x][:supposed] = (sum[x][:supposed] || 0) + 1}
      r.each {|x| sum[x] ||= {}; sum[x][:real] = (sum[x][:real] || 0) + 1}
      v.each {|x| sum[x] ||= {}; sum[x][:valid] = (sum[x][:valid] || 0) + 1}
      sum
    end

    result.map do |k,v|
      if v[:supposed]
        paper = PaperTypeRepo[k]
        v[:real] ||= 0
        v[:valid] ||= 0
        {
          paper_type: {id: paper.id, name: paper.name},
          numbers: v,
          ratio: v[:valid].to_f / v[:supposed].to_f * 100
        }
      end
    end.compact
  end


  
  def self.lost
    result = []

    JobRepo.all.each do |job|
      organ_id = job["organ"]["id"]
      position_id = job["subject"]["id"]
      job["assign"].each do |user|
        losts = require_papers(organ_id, position_id) - register_papers(user["login"])
        unless losts.empty?
          result << {
            employee: {id: user["login"], name: user["name"]},
            job: {organ: job["organ"]["name"], position: job["subject"]["name"]},
            lost_papers: PaperTypeRepo.where(id: losts).map{|e| {id: e.id, name: e.name}}
          }
        end                              
      end
    end

    result
  end



  
  def self.due_date to
    employees = EmployeeRepo.all.inject({}) do |sum, e|
      sum.merge({e["login"] => e["name"]})
    end

    users = PaperRegisterRepo.all.map(&:employee_id)
    all   = PaperRegisterRepo.all.map do |paper|
      paper if paper.due_date <= to || (paper.due_date - paper.paper_type.delay) <= to
    end.compact

    
    users.map do |emp|
      {
        employee: {id: emp, name: employees[emp]},
        duedate_papers:
          all.clone.keep_if {|x| x.employee_id == emp}.map {|x| x.perfect.tap {|h| h.delete(:employee)}}
      }
    end
  end


  private
  def self.require_papers(organ_id, position_id)
    OrganRegisterRepo.where(organ_id: organ_id).map do |e|
      PaperRequireRepo.where(manager_id: e.manager_id, position_id: position_id).map(&:paper_type_id)
    end.flatten.uniq
  end

  def self.register_papers(user_id)
    PaperRegisterRepo.where(employee_id: user_id).map(&:paper_type_id)
  end

end
